It is commonplace to extend the functionality of an existing application such as MICROSOFT EXCEL® by developing an “add-in”. An add-in is typically not written by the creators of the host application but by third party developers that want to extend the functionality of the host application. An add-in can be created with development tools such as VISUAL STUDIO .NET 2005® and VISUAL STUDIO 2005 TOOLS FOR APPLICATIONS®. An add-in is a component that a host application such as MICROSOFT EXCEL® loads when it is needed such as when the host application starts up or when a particular document is loaded by the host application.
A host application may choose to execute an add-in in a separate process for several reasons including process stability, platform version resilience, or special debugging scenarios. Running an add-in in a separate process requires a mechanism for the host application and the add-in to communicate across process boundaries. There exist several Remote Procedure Call (RPC) technologies a host may use for this communication. However, there are several problems specific to the host/add-in model that require special considerations that most RPC technologies do not consider. The most notable of these problems is threading model of the host and of the add-in.
MICROSOFT® .NET is an example of a set of technologies that provide a managed code environment. .NET managed code has access to all the services that the Common Language Runtime (CLR) technology makes available, such as cross-language integration, security and versioning support, and garbage collection. Code that does not operate within a runtime managed framework such as CLR is called unmanaged code.
In the .NET environment, the standard RPC technology is .NET Remoting. .NET Remoting provides an interprocess communication manager for managed code. .NET Remoting makes remote procedure calls transparent, i.e., invisible, to the caller/callee. That is, a first object may call a method on a second object which exists in a separate process without the first object knowing that the call is remote. .NET Remoting intercepts the call to the second object via a proxy and transports that call to the other process. However, in the current .NET Remoting implementation each call across process executes on a different thread in the target process. This can cause many problems for add-ins which normally run on a specific thread within the host application. If the add-in uses a technology which expects thread affinity, that technology will fail when the add-in is moved to an external process and called from multiple remoting threads. An example of such a technology is MICROSOFT WINDOWS® Timers.
A related problem occurs in the multitudes of unmanaged applications written using, for example, MICROSOFT's® Common Object Model (COM) technology. COM technologies provide, among other things, an interprocess communication manager for unmanaged code. In COM applications, it is common practice for a thread within the application to be marked as a “Single-Threaded Apartment”. Any call into objects within this apartment must first be marshaled onto the apartment's thread (i.e. transferred to execute on the thread contained within the apartment). COM keeps track of the incoming and out-going calls within the apartment. The collection of these calls is called the logical thread. When a new call enters the apartment, this call is called the “top-level call” of the logical thread. If a call leaves the apartment by calling an object outside the apartment boundaries (either cross-process or cross apartment) incoming top-level calls will be blocked by COM. If the out-going call results in a new call coming in, that call is part of the current logical thread and is allowed to enter the apartment. Only calls which are part of the current logical thread are allowed to re-enter the apartment. This means the current .NET Remoting technology is unacceptable for communication between a COM host and its add-ins. If the com host was to make a call to an add-in using .NET Remoting, and that call executed on a different thread in the add-in, calls back to the host would appear to be a different top-level call to COM and would be rejected.